# -*- encoding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    Parthiv PATEL
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import twitter
import time
import netsvc
from osv import fields, osv
import ir
import pooler
import mx.DateTime
from mx.DateTime import RelativeDateTime
from tools import config
from tools.translate import _
from xml import dom


from mx import DateTime
from mx.DateTime import now
import time

import netsvc
from osv import fields, osv
import ir

class one2many_mod_dm(fields.one2many):
    def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
        
        if not context:
            context = {}
        if self._context:
            context = context.copy()
        context.update(self._context)
        if not values:
            values = {}
        res = {}
        for id in ids:
            res[id] = []
        ids2 = obj.pool.get(self._obj).search(cr, user, [('dm','=',1),(self._fields_id, 'in', ids)], limit=self._limit, context=context)        
        for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
            res[r[self._fields_id]].append(r['id'])        
        return res

class one2many_mod_dm_sent(fields.one2many):
    def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
        
        if not context:
            context = {}
        if self._context:
            context = context.copy()
        context.update(self._context)
        if not values:
            values = {}
        res = {}
        for id in ids:
            res[id] = []
        ids2 = obj.pool.get(self._obj).search(cr, user, [('dm_sent','=',1),(self._fields_id, 'in', ids)], limit=self._limit, context=context)        
        for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
            res[r[self._fields_id]].append(r['id'])        
        return res



class one2many_mod_men(fields.one2many):
    def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
        
        if not context:
            context = {}
        if self._context:
            context = context.copy()
        context.update(self._context)
        if not values:
            values = {}
        res = {}
        for id in ids:
            res[id] = []
        ids2 = obj.pool.get(self._obj).search(cr, user, [('mention','=',1),(self._fields_id, 'in', ids)], limit=self._limit, context=context)        
        for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
            res[r[self._fields_id]].append(r['id'])        
        return res

class one2many_mod_twit(fields.one2many):
    def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
        
        if not context:
            context = {}
        if self._context:
            context = context.copy()
        context.update(self._context)
        if not values:
            values = {}
        res = {}
        for id in ids:
            res[id] = []
        ids2 = obj.pool.get(self._obj).search(cr, user, [('twit','=',1),(self._fields_id, 'in', ids)], limit=self._limit, context=context)        
        for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
            res[r[self._fields_id]].append(r['id'])        
        return res


class twit_people(osv.osv):
    _name='twit.people'
    _columns = {
            'name':fields.char('Name',size=32),
            'twiter_id':fields.char('Twitter ID',size=32),
            'verified':fields.boolean('Verified ?'),
            'location':fields.char('Location',size=64),
            'description':fields.text('Desc.'),
            'screen_name':fields.char('Screen Name',size=64),
            'following':fields.boolean('Following ?'),
            'time_zone':fields.char('Time Zone',size=64),
            'url':fields.char('URL',size=256),            
            }
twit_people()

class twit_data(osv.osv):    
    _name="twit.data"
    
    def get_authetication(self,cr,uid,ids,*args):        
        self_obj=self.browse(cr,uid,ids[0])
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            creds=api.GetCredentials()
                        
            data={
                  'twiter_id':creds.id,
                  'screen_name':creds.screen_name,                  
                  'state':'auth'
                  }
            self.write(cr,uid,ids[0],data)
        except Exception, e:            
            print e
            raise osv.except_osv(_('Error !'), _("Authentication failed with your provided credentials."))
        return True

    
    def _get_people_id(self,cr,uid,api,message,*args):        
        if args and args[0]==1:
                people_id=self.pool.get('twit.people').search(cr,uid,[('twiter_id','=',message.recipient_id)])            
        else:
            try:
                people_id=self.pool.get('twit.people').search(cr,uid,[('twiter_id','=',message.sender_id)])
            except:
                people_id=self.pool.get('twit.people').search(cr,uid,[('twiter_id','=',message.id)])
        
        
        if people_id:            
            return people_id[0]
        elif args and args[0]==1:            
            sender=api.GetUser(message.recipient_screen_name)
        else:
            try:
                sender=api.GetUser(message.sender_screen_name)
            except:                
                sender=api.GetUser(message.screen_name)
                    
            data={
                  'name':sender.name or None,
                  'twiter_id':sender.id or None,
                  'verified':sender.verified or None,
                  'location':sender.location or None,
                  'description':sender.description or None,
                  'screen_name':sender.screen_name or None,
                  'following':sender.following or None,
                  'time_zone':sender.time_zone or None,
                  'url':sender.url,                  
                  }
            people_id=self.pool.get('twit.people').create(cr,uid,data)            
            
            return people_id
                    
    def get_mentions(self,cr,uid,ids,*args):
        self_obj=self.browse(cr,uid,ids[0])
        temp_lst=[]        
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            api.SetCacheTimeout(10)
            direct_messages =api.getUserMentions()
             
            message_ids=self.pool.get('twit.direct.message').search(cr,uid,[('twit_config_id','=',ids[0])])
            twit_message_ids=self.pool.get('twit.direct.message').read(cr,uid,message_ids,['message_id'])
            twit_msg_ids=[x['message_id'] for x in twit_message_ids]
            
            
            for message in direct_messages:                
                if message.id not in twit_msg_ids:
                    data={
                    'twit_people_id':self._get_people_id(cr,uid,api,message), 
                    'message_id':message.id,
                    'text':message.text,
                    'created_at':message.created_at,
                    'twit_config_id':ids[0],
                    'mention':1,
                        }
                    temp_lst.append([0,0,data])
            
            self.write(cr,uid,ids[0],{'direct_twit_lines':temp_lst})
                    
        except Exception, e:
            print e
            raise osv.except_osv(_('Error !'), _("Error In Getting Mentions.")) 
        return True        

    def get_dm(self,cr,uid,ids,*args):
        self_obj=self.browse(cr,uid,ids[0])
        temp_lst=[]
        
        dm_inbox_message_ids=self.pool.get('twit.direct.message').search(cr,uid,[('twit_config_id','=',ids[0]),('dm','=',1)])
        twit_inbox_message_ids=self.pool.get('twit.direct.message').read(cr,uid,dm_inbox_message_ids,['message_id'])
        twit_inbox_msg_ids=[x['message_id'] for x in twit_inbox_message_ids]
        
        dm_sent_message_ids=self.pool.get('twit.direct.message').search(cr,uid,[('twit_config_id','=',ids[0]),('dm_sent','=',1)])
        twit_sent_message_ids=self.pool.get('twit.direct.message').read(cr,uid,dm_sent_message_ids,['message_id'])
        twit_sent_msg_ids=[x['message_id'] for x in twit_sent_message_ids]
        
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            if twit_inbox_msg_ids:
                direct_messages_inbox = api.GetDirectMessages(since_id=twit_inbox_msg_ids[0])
            else:
                direct_messages_inbox = api.GetDirectMessages()
            if twit_sent_msg_ids:
                direct_messages_sent = api.GetSentDirectMessages(since_id=twit_sent_msg_ids[0])
            else:
                direct_messages_sent = api.GetSentDirectMessages()
            
            api.SetCacheTimeout(10)
            
            
            for message in direct_messages_inbox:                
                if message.id not in twit_inbox_msg_ids:
                    data={
                    'twit_people_id':self._get_people_id(cr,uid,api,message), 
                    'message_id':message.id,
                    'text':message.text,
                    'created_at':message.created_at,
                    'twit_config_id':ids[0],
                    'dm':1,
                        }
                    temp_lst.append([0,0,data])
                    
            for message in direct_messages_sent:                                     
                if message.id not in twit_sent_msg_ids:
                    data={ 
                    'twit_people_id':self._get_people_id(cr,uid,api,message,1),
                    'message_id':message.id,
                    'text':message.text,
                    'created_at':message.created_at,
                    'twit_config_id':ids[0],
                    'dm_sent':1,
                        }
                    temp_lst.append([0,0,data])
            
            self.write(cr,uid,ids[0],{'direct_twit_lines':temp_lst})
                    
        except Exception, e:
            print e
            raise osv.except_osv(_('Error !'), _("Error In Getting Mentions."))
        return True        

    def make_twit(self,cr,uid,ids,*args):
        self_obj=self.browse(cr,uid,ids[0])
        temp_lst=[]        
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            direct_messages =api.PostUpdate(self_obj.my_twit)
            api.SetCacheTimeout(10)
            self.write(cr,uid,ids[0],{'twit_state':'twitted'})
        except Exception, e:
            self.write(cr,uid,ids[0],{'twit_state':'fail'})
            raise osv.except_osv(_('Error !'), _("Text must be less than or equal to 140 characters."))
        return True

    def onchange_my_twit(self,cr,uid,args,my_twit):
        if not my_twit:
            return {'value':{'twit_len':0}}
        else:
            return {'value':{'twit_len':len(my_twit)}}

    def get_followers(self,cr,uid,ids,*args):
        self_obj=self.browse(cr,uid,ids[0])
        follower_lst=[]
        temp2_lst=[]
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            followers =api.GetFollowers()
            api.SetCacheTimeout(10)
            follower_ids=self.read(cr,uid,ids[0],['followers_ids'])
            if follower_ids['followers_ids']:
                f_data=self.pool.get('twit.people').browse(cr,uid,follower_ids['followers_ids'])                
                follower_lst=[f.twiter_id for f in f_data]
            for follower in followers:
                if str(follower.id) not in followers:
                        temp2_lst.append(self._get_people_id(cr,uid,api,follower))
            
            self.write(cr,uid,ids[0],{'followers_ids':[[6,0,temp2_lst]]})
            
        except Exception, e:            
            print e            
            raise osv.except_osv(_('Error !'), _("Error in fetching followers !!!"))
        return True

    def get_twits(self,cr,uid,ids,*args):
        
        self_obj=self.browse(cr,uid,ids[0])
        follower_lst=[]        
        temp_lst=[]
        
        message_ids=self.pool.get('twit.direct.message').search(cr,uid,[('twit_config_id','=',ids[0])])
        
        twit_message_ids=self.pool.get('twit.direct.message').read(cr,uid,message_ids,['message_id'])
        twit_msg_ids=[x['message_id'] for x in twit_message_ids]
        
        
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            api.SetCacheTimeout(10)
            
            if twit_msg_ids:                
                timeline=api.GetUserTimeline(since_id=twit_msg_ids[0])                
            else:                
                timeline=api.GetUserTimeline()
            
            for message in timeline:                
                if message.id not in twit_msg_ids:
                    data={ 
                    'message_id':message.id,
                    'text':message.text,
                    'created_at':message.created_at,
                    'twit_config_id':ids[0],
                    'twit':1,
                        }
                    temp_lst.append([0,0,data])
            
            self.write(cr,uid,ids[0],{'direct_twit_lines':temp_lst})
                    
        except Exception, e:
            print e
            raise osv.except_osv(_('Error !'), _("Error In Getting Twits."))
        return True        
    
    def onchange_my_dm(self,cr,uid,args,my_dm):
        if not my_dm:
            return {'value':{'msg_len':0}}
        else:
            return {'value':{'msg_len':len(my_dm)}}

    def send_dm(self,cr,uid,ids,*args):
        self_obj=self.browse(cr,uid,ids[0])
        to_user=self_obj.message_to_user_id.twiter_id
        text=self_obj.my_dm
        try:
            api=twitter.Api(username=self_obj.user_name, password=self_obj.password)
            api.SetCacheTimeout(10)
            api.PostDirectMessage(to_user,text)
            self.write(cr,uid,ids[0],{'dm_state':'sent'})
        except Exception, e:
            print e
            self.write(cr,uid,ids[0],{'dm_state':'fail'})
            raise osv.except_osv(_('Error !'), _("Error In Sending Message."))
        return True
    
    def refresh_all(self,cr,uid,ids,args):
        self.get_twits(cr, uid, ids)
        self.get_mentions(cr, uid, ids)        
        self.get_dm(cr, uid, ids)
        self.get_followers(cr, uid, ids)
        return True
    _columns = {
        'name':fields.char('Name',size=32),
        'user_name':fields.char('Twitter User Name',size=32),
        'password':fields.char('Twitter Password',invisible=True,size=64),
        'screen_name':fields.char('Twitter Screen Name',size=32),
        'twiter_id':fields.char('Twitter ID',size=64,readonly=True),
        'cur_stat':fields.char('Status',size=256),
        'state':fields.selection([('draft','Draft'),('auth','Authorized'),('unauth','Unauthorized')],'State',required=True,readonly=True),
        'direct_message_lines':one2many_mod_dm('twit.direct.message','twit_config_id','Inbox Direct Messages'),
        'direct_sent_message_lines':one2many_mod_dm_sent('twit.direct.message','twit_config_id','Sent Direct Messages'),
        'direct_mention_lines':one2many_mod_men('twit.direct.message','twit_config_id','Mentions'),
        'direct_twit_lines':one2many_mod_twit('twit.direct.message','twit_config_id','My Twits'),
        'my_twit':fields.text('Twit'),
        'twit_state':fields.selection([('twitted','Twitted'),('fail','Fail'),('draft','Draft')],'Twit State',required=True,readonly=True),
        'twit_len':fields.integer("Twit Length",readonly=True),
        'followers_ids':fields.many2many('twit.people','twit_config_people_rel','config_id','follower_id'),
        'my_dm':fields.text('Direct Message'),
        'msg_len':fields.integer("Message Length",readonly=True),
        'dm_state':fields.selection([('sent','Sent'),('fail','Fail'),('draft','Draft')],'Message State',required=True,readonly=True),
        'message_to_user_id':fields.many2one('twit.people',"Send To"),
    }
    _defaults = {
        'state': lambda *a: 'draft',
        'twit_state': lambda *a: 'draft',
        'dm_state': lambda *a: 'draft',
    } 
twit_data()



class twit_direct_message(osv.osv):
    _name='twit.direct.message'
    _rec_name='twit_people_id'
    _order='created_at desc'
    
    def unlink(self, cr, uid, ids, *args, **kwargs):
        for message in self.browse(cr, uid, ids):
            if message.twit or message.dm or message.dm_sent:
                pass
                # TODO: delete Twits, direct messages from twitter account                                                
        return super(twit_direct_message, self).unlink(cr, uid, ids, *args, **kwargs)            
        
                
    
    _columns = {                
        'message_id':fields.integer_big('Message ID'),
        'created_at':fields.datetime('Created At',readonly=True),
        'text':fields.char('Text',size=256,readonly=True),
        'twit_people_id':fields.many2one('twit.people','Sender'),
        'twit_config_id':fields.many2one('twit.data','Twit Config'),
        'dm':fields.boolean('Direct Message ?'),
        'twit':fields.boolean('Twit ?'),
        'mention':fields.boolean('Mention ?'),
        'dm_sent':fields.boolean('Direct Message Sent?'),
    }
twit_direct_message()